home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume4 / vms-vi-2 / part13 < prev    next >
Encoding:
Internet Message Format  |  1989-02-03  |  33.9 KB

  1. Path: xanth!mcnc!gatech!cwjcc!hal!ncoast!allbery
  2. From: gregg@a.cs.okstate.edu (Gregg Wonderly)
  3. Newsgroups: comp.sources.misc
  4. Subject: v04i104: TPUVI for VMS part 13 of 17
  5. Message-ID: <8809220235.AA04173@uunet.UU.NET>
  6. Date: 27 Sep 88 22:17:44 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: gregg@a.cs.okstate.edu (Gregg Wonderly)
  9. Lines: 1503
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. Posting-number: Volume 4, Issue 104
  13. Submitted-by: "Gregg Wonderly" <gregg@a.cs.okstate.edu>
  14. Archive-name: vms-vi-2/Part13
  15.  
  16. $ WRITE SYS$OUTPUT "Creating ""VI.9"""
  17. $ CREATE VI.9
  18. $ DECK/DOLLARS=$$EOD$$
  19.     IF (token_1 = "nomagic") THEN
  20.         vi$magic := 0;
  21.         RETURN (0);
  22.     ENDIF;
  23.  
  24.     IF (token_1 = "noerrorbells") OR (token_1 = "noeb") THEN
  25.         vi$error_bells := 0;
  26.         RETURN (0);
  27.     ENDIF;
  28.  
  29.     IF (token_1 = "errorbells") OR (token_1 = "eb") THEN
  30.         vi$error_bells := 1;
  31.         RETURN (0);
  32.     ENDIF;
  33.  
  34.     IF (token_1 = "nowrapscan") OR (token_1 = "nows") THEN
  35.         vi$wrap_scan := 0;
  36.         RETURN (0);
  37.     ENDIF;
  38.  
  39.     IF (token_1 = "wrapscan") OR (token_1 = "ws") THEN
  40.         vi$wrap_scan := 1;
  41.         RETURN (0);
  42.     ENDIF;
  43.  
  44.     IF (token_1 = "noupdate") THEN
  45.         vi$min_update := 1;
  46.         RETURN (0);
  47.     ENDIF;
  48.  
  49.     IF (token_1 = "update") THEN
  50.         vi$min_update := 0;
  51.         RETURN (0);
  52.     ENDIF;
  53.  
  54.     IF (token_1 = "noshowmode") OR (token_1 = "nosm") THEN
  55.         vi$show_mode := 0;
  56.         RETURN (0);
  57.     ENDIF;
  58.  
  59.     IF (token_1 = "showmode") OR (token_1 = "sm") THEN
  60.         vi$show_mode := 1;
  61.         RETURN (0);
  62.     ENDIF;
  63.  
  64.     IF (token_1 = "wrapmargin") OR (token_1 = "wm") THEN
  65.         token_2 := vi$skip_separ (cmd, i, "= "+ASCII(9), separ);
  66.         vi$wrap_margin := INT (token_2);
  67.         RETURN (0);
  68.     ENDIF;
  69.  
  70.     IF (token_1 = "sections") OR (token_1 = "sect") THEN
  71.         pstr := "LINE_BEGIN&((";
  72.         use_fortran := 0;
  73.         vi$sect_str := "";
  74.         LOOP
  75.             EXITIF (SUBSTR (cmd, i, 1) = " ") OR (i >= LENGTH (cmd));
  76.             npat := SUBSTR (cmd, i, 2);
  77.             vi$sect_str := vi$sect_str + npat;
  78.             EDIT (npat, COLLAPSE);
  79.             IF (npat = "+c") OR (npat = "+C") THEN
  80.                 pstr := pstr + '"{"';
  81.             ELSE
  82.                 IF (npat = "+f") OR (npat = "+F") THEN
  83.                     use_fortran := 1;
  84.                     npat := "";
  85.                 ELSE
  86.                     IF (npat = "+t") OR (npat = "+T") THEN
  87.                         pstr := pstr + '"PROCEDURE"';
  88.                     ELSE
  89.                         pstr := pstr + '".' + npat + '"';
  90.                     ENDIF;
  91.                 ENDIF;
  92.             ENDIF;
  93.             i := i + 2;
  94.             EXITIF (SUBSTR (cmd, i, 1) = " ") OR (i >= LENGTH (cmd));
  95.             IF (npat <> "") THEN
  96.                 pstr := pstr + "|";
  97.             ENDIF;
  98.         ENDLOOP;
  99.         pstr := pstr + ")";
  100.         IF (use_fortran) THEN
  101.             pstr := '("FUNCTION"|"SUBROUTINE")|('+ pstr + "))|LINE_END)";
  102.         ENDIF;
  103.         EXECUTE (COMPILE ("vi$sect_pat:="+pstr+";"));
  104.         RETURN (0);
  105.     ENDIF;
  106.  
  107.     IF (token_1 = "paragraphs") OR (token_1 = "para") THEN
  108.         pstr := 'LINE_BEGIN&((';
  109.         vi$para_str := "";
  110.         LOOP
  111.             EXITIF (SUBSTR (cmd, i, 1) = " ") OR (i >= LENGTH (cmd));
  112.             npat := SUBSTR (cmd, i, 2);
  113.             vi$para_str := vi$para_str + npat;
  114.             EDIT (npat, COLLAPSE);
  115.             pstr := pstr + '".' + npat + '"';
  116.             i := i + 2;
  117.             EXITIF (SUBSTR (cmd, i, 1) = " ") OR (i >= LENGTH (cmd));
  118.             IF (npat <> "") THEN
  119.                 pstr := pstr + "|";
  120.             ENDIF;
  121.         ENDLOOP;
  122.         pstr := pstr + ")|LINE_END)";
  123.         EXECUTE (COMPILE ("vi$para_pat:="+pstr+";"));
  124.         RETURN (0);
  125.     ENDIF;
  126.  
  127.     IF (token_1 = "number") OR
  128.             (token_1 = "optimize") OR
  129.             (token_1 = "noautoprint") OR
  130.             (token_1 = "novice") OR
  131.             (token_1 = "slowopen") OR
  132.             (token_1 = "noslowopen") OR
  133.             (token_1 = "beautify") OR
  134.             (token_1 = "taglength") OR
  135.             (token_1 = "directory") OR
  136.             (token_1 = "noprompt") OR
  137.             (token_1 = "edcompatible") OR
  138.             (token_1 = "term") OR
  139.             (token_1 = "noredraw") OR
  140.             (token_1 = "redraw") OR
  141.             (token_1 = "terse") OR
  142.             (token_1 = "flash") OR
  143.             (token_1 = "noremap") OR
  144.             (token_1 = "timeout") OR
  145.             (token_1 = "hardtabs") OR
  146.             (token_1 = "ttytype") OR
  147.             (token_1 = "warn") OR
  148.             (token_1 = "nowarn") OR
  149.             (token_1 = "lisp") OR
  150.             (token_1 = "list") OR
  151.             (token_1 = "sh") OR
  152.             (token_1 = "shell") OR
  153.             (token_1 = "mesg") OR
  154.             (token_1 = "nomesg") OR
  155.             (token_1 = "showmatch") THEN
  156.         vi$not_implemented (token_1);
  157.         RETURN (1);
  158.     ENDIF;
  159.  
  160.     vi$info ("Unrecognized option ("+token_1+
  161.                                     "), use `set all' to see options.");
  162.     RETURN (1);
  163.  
  164. ENDPROCEDURE;
  165.  
  166. !
  167. !   Set the window length to the integer value passed.
  168. !
  169. PROCEDURE vi$do_set_window (len)
  170.     LOCAL
  171.         buf,
  172.         curwin,
  173.         curbuf;
  174.  
  175.     curwin := CURRENT_WINDOW;
  176.     curbuf := CURRENT_BUFFER;
  177.  
  178.     IF (vi$prev_win (curwin) = 0) AND (vi$next_win (curwin) = 0)
  179.                                             AND (NOT vi$in_occlusion) THEN
  180.         IF len < 3 THEN
  181.             len := 3;
  182.         ENDIF;
  183.  
  184.         IF len > GET_INFO (SCREEN, "VISIBLE_LENGTH") THEN
  185.             len := GET_INFO (SCREEN, "VISIBLE_LENGTH");
  186.         ENDIF;
  187.  
  188.         oldscrlen := vi$scr_length;
  189.         vi$scr_length := len;
  190.  
  191.         ADJUST_WINDOW (curwin, 0, vi$scr_length - oldscrlen);
  192.  
  193.         buf := GET_INFO (message_window, "BUFFER");
  194.         UNMAP (message_window);
  195.         DELETE (message_window);
  196.         message_window := CREATE_WINDOW (vi$scr_length - 1, 2, ON);
  197.         MAP (message_window, buf);
  198.         SET (STATUS_LINE, message_window, NONE, "");
  199.         ADJUST_WINDOW (message_window, 1, 0);
  200.  
  201.         DELETE (command_window);
  202.         command_window := CREATE_WINDOW (vi$scr_length, 1, OFF);
  203.  
  204.         buf := GET_INFO (info_window, "BUFFER");
  205.         DELETE (info_window);
  206.         info_window := CREATE_WINDOW (1, vi$scr_length - 1, ON);
  207.         SET (STATUS_LINE, info_window, NONE, "");
  208.  
  209.         SET (PROMPT_AREA, vi$scr_length, 1, REVERSE);
  210.  
  211.         POSITION (curbuf);
  212.         POSITION (curwin);
  213.         UNMAP (curwin);
  214.         MAP (curwin, curbuf);
  215.     ELSE
  216.         vi$info (
  217.         "Can't change length of screen while multiple windows visible!");
  218.         RETURN (1);
  219.     ENDIF;
  220.  
  221.     vi$how_much_scroll := vi$scr_length / 2;
  222.     RETURN (0);
  223. ENDPROCEDURE;
  224.  
  225. !
  226. !   Show the current settings when ":set all" is issued.
  227. !
  228. PROCEDURE vi$show_settings
  229.     LOCAL
  230.         bname,
  231.         readonly,
  232.         obuf,
  233.         ic,
  234.         ostat,
  235.         ovid,
  236.         buf;
  237.  
  238.     buf := vi$init_buffer ("$$vi_set_all$$", "");
  239.  
  240.     ostat := GET_INFO (CURRENT_WINDOW, "STATUS_LINE");
  241.     IF (ostat = 0) THEN
  242.         ostat := "";
  243.     ENDIF;
  244.     ovid := GET_INFO (CURRENT_WINDOW, "STATUS_VIDEO");
  245.     IF (ovid = 0) THEN
  246.         ovid := NONE;
  247.     ENDIF;
  248.     SET (STATUS_LINE, CURRENT_WINDOW, NONE, "");
  249.     SET (STATUS_LINE, CURRENT_WINDOW, REVERSE,
  250.         "                      Current settings of VI options");
  251.     SET (EOB_TEXT, buf,
  252.                 "                      [Hit ENTER to continue editing]");
  253.     obuf := CURRENT_BUFFER;
  254.     POSITION (buf);
  255.  
  256.     IF vi$ignore_case = EXACT THEN
  257.         ic := 2;
  258.     ELSE
  259.         ic := 0;
  260.     ENDIF;
  261.  
  262.     COPY_TEXT (FAO (
  263.     "!20<wrapmargin=!UL!>!20<tabstop=!UL!>!20<!ASmagic!>!20<!ASignorecase!>",
  264.             vi$wrap_margin, vi$tab_amount,
  265.             SUBSTR ("no", 1, (1-vi$magic)*2),
  266.             SUBSTR ("no", 1, ic)));
  267.  
  268.     SPLIT_LINE;
  269.  
  270.     COPY_TEXT (FAO (
  271.     "!20<shiftwidth=!UL!>!20<scroll=!UL!>!20<report=!UL!>!20<!ASautowrite!>",
  272.             vi$shift_width, vi$how_much_scroll, vi$report,
  273.             SUBSTR ("no", 1, (1-vi$auto_write)*2)));
  274.  
  275.     SPLIT_LINE;
  276.  
  277.     COPY_TEXT (FAO (
  278.             "!20<!ASwrapscan!>!20<!ASupdate!>!20<!AStabs!>!20<!ASundomap!>",
  279.             SUBSTR ("no", 1, (1-vi$wrap_scan)*2),
  280.             SUBSTR ("no", 1, (vi$min_update)*2),
  281.             SUBSTR ("no", 1, (1-vi$use_tabs)*2),
  282.             SUBSTR ("no", 1, (1-vi$undo_map)*2)
  283.         ));
  284.  
  285.     SPLIT_LINE;
  286.  
  287.     IF vi$tag_case = EXACT THEN
  288.         ic := 0;
  289.     ELSE
  290.         ic := 2;
  291.     ENDIF;
  292.  
  293.     COPY_TEXT (FAO (
  294.             "!20<!AStagcase!>!20<window=!UL!>!20<width=!UL!>tags=!AS",
  295.             SUBSTR ("no", 1, ic),
  296.             GET_INFO (CURRENT_WINDOW, "VISIBLE_LENGTH"),
  297.             GET_INFO (CURRENT_WINDOW, "WIDTH"),
  298.             vi$tag_files
  299.         ));
  300.  
  301.     SPLIT_LINE;
  302.  
  303.     COPY_TEXT (FAO (
  304.             "!20<!ASerrorbells!>!20<paragraphs=!AS!>!20<sections=!AS!>"+
  305.                 "!20<!ASsenddcl!>",
  306.             SUBSTR ("no", 1, (1-vi$error_bells)*2),
  307.             vi$para_str,
  308.             vi$sect_str,
  309.             SUBSTR ("no", 1, (1-vi$send_dcl)*2)
  310.         ));
  311.  
  312.     SPLIT_LINE;
  313.  
  314.     readonly := vi$getbufmode (obuf);
  315.     COPY_TEXT (FAO (
  316.         "!20<!ASshowmode!>!20<!ASautoindent!>!20<!ASempty!>!20<!ASreadonly!>",
  317.             SUBSTR ("no", 1, (1-vi$show_mode)*2),
  318.             SUBSTR ("no", 1, (1-vi$auto_indent)*2),
  319.             SUBSTR ("no", 1, (vi$delete_empty)*2),
  320.             SUBSTR ("no", 1, (1-readonly)*2)
  321.         ));
  322.  
  323.     SPLIT_LINE;
  324.  
  325.     MAP (CURRENT_WINDOW, buf);
  326.     UPDATE (CURRENT_WINDOW);
  327.     LOOP
  328.         EXITIF vi$read_a_key = RET_KEY;
  329.     ENDLOOP;
  330.  
  331.     SET (STATUS_LINE, CURRENT_WINDOW, NONE, "");
  332.     SET (STATUS_LINE, CURRENT_WINDOW, ovid, ostat);
  333.     MAP (CURRENT_WINDOW, obuf);
  334.     POSITION (obuf);
  335.     DELETE (buf);
  336. ENDPROCEDURE;
  337.  
  338. !
  339. !
  340. !
  341. PROCEDURE vi$makebufname (buf)
  342.     LOCAL
  343.         i,
  344.         ch,
  345.         bname,
  346.         nname;
  347.  
  348.     nname := "";
  349.     bname := GET_INFO (buf, "NAME");
  350.  
  351.     i := 1;
  352.     LOOP
  353.         EXITIF i > LENGTH (bname);
  354.         ch := SUBSTR (bname, i, 1);
  355.         IF INDEX (vi$_sym_chars, ch) <> 0 THEN
  356.             nname := nname + ch;
  357.         ENDIF;
  358.         i := i + 1;
  359.     ENDLOOP;
  360.  
  361.     RETURN (nname);
  362. ENDPROCEDURE;
  363.  
  364. !
  365. !
  366. !
  367. PROCEDURE vi$getbufmode (buf)
  368.     LOCAL
  369.         nname;
  370.  
  371.     ON_ERROR
  372.         RETURN (1);
  373.     ENDON_ERROR;
  374.  
  375.     IF (GET_INFO (buf, "SYSTEM")) THEN
  376.         RETURN (1);
  377.     ELSE
  378.         nname := vi$makebufname (buf);
  379.         vi$global_var := 0;
  380.         EXECUTE (COMPILE ("vi$global_var := vi$bmode_"+nname));
  381.         RETURN (vi$global_var);
  382.     ENDIF;
  383. ENDPROCEDURE;
  384.  
  385. !
  386. !
  387. !
  388. PROCEDURE vi$setbufmode (buf, bmode)
  389.     LOCAL
  390.         nname;
  391.  
  392.     nname := vi$makebufname (buf);
  393.     EXECUTE (COMPILE ("vi$bmode_"+nname+":="+STR(bmode)));
  394. ENDPROCEDURE;
  395.  
  396. !
  397. !   Function to say that a particular command is not implemented.
  398. !
  399. PROCEDURE vi$not_implemented (cmd)
  400.     vi$info (cmd + " is not implemented!");
  401. ENDPROCEDURE;
  402.  
  403. !
  404. !   The function mapped to 't'.
  405. !
  406. PROCEDURE vi$_to_char (char_to_find)
  407.     LOCAL
  408.         char_val;
  409.  
  410.     char_val := char_to_find;
  411.     vi$beep_position (vi$to_char (char_val), 0, 1);
  412. ENDPROCEDURE;
  413.  
  414. !
  415. !   Function performing task for 't'.
  416. !
  417. PROCEDURE vi$to_char (ch_to_find)
  418.  
  419.     LOCAL
  420.         char_to_find,
  421.         act_count,
  422.         pos,
  423.         found;
  424.  
  425.     char_to_find := ch_to_find;
  426.     IF char_to_find = 0 THEN
  427.         char_to_find := vi$read_char_to_find;
  428.     ENDIF;
  429.  
  430.     vi$last_s_char := char_to_find;
  431.     vi$last_s_func := "vi$to_char";
  432.  
  433.     pos := MARK(NONE);
  434.  
  435.     act_count := vi$cur_active_count;
  436.  
  437.     IF (MARK (NONE) = END_OF (CURRENT_BUFFER)) THEN
  438.         RETURN (0);
  439.     ENDIF;
  440.  
  441.     MOVE_HORIZONTAL (1);
  442.  
  443.     IF char_to_find <> ASCII(27) THEN
  444.         found := 0;
  445.         LOOP
  446.             EXITIF (CURRENT_OFFSET >= LENGTH (vi$current_line));
  447.             MOVE_HORIZONTAL (1);
  448.             found := 1;
  449.             IF (CURRENT_CHARACTER = char_to_find) THEN
  450.                 act_count := act_count - 1;
  451.                 EXITIF (act_count = 0);
  452.             ENDIF;
  453.             found := 0;
  454.         ENDLOOP;
  455.  
  456.         IF (NOT found) THEN
  457.             POSITION (pos);
  458.             RETURN (0);
  459.         ELSE
  460.             vi$move_horizontal (-1);
  461.         ENDIF;
  462.     ENDIF;
  463.  
  464.     vi$yank_mode := VI$IN_LINE_MODE;
  465.     RETURN (vi$retpos (pos));
  466.  
  467. ENDPROCEDURE;
  468.  
  469. !
  470. !   The function mapped to 'T'.
  471. !
  472. PROCEDURE vi$_back_to_char (char_to_find)
  473.  
  474.     LOCAL
  475.         char_val;
  476.  
  477.     char_val := char_to_find;
  478.     vi$beep_position (vi$back_to_char (char_val), 0, 1);
  479. ENDPROCEDURE;
  480.  
  481. !
  482. !   Function performing task for 'T'.
  483. !
  484. PROCEDURE vi$back_to_char (ch_to_find)
  485.  
  486.     LOCAL
  487.         char_to_find,
  488.         act_count,
  489.         pos,
  490.         found;
  491.  
  492.     char_to_find := ch_to_find;
  493.     IF char_to_find = 0 THEN
  494.         char_to_find := vi$read_char_to_find;
  495.     ENDIF;
  496.  
  497.     vi$last_s_char := char_to_find;
  498.     vi$last_s_func := "vi$back_to_char";
  499.  
  500.     pos := MARK(NONE);
  501.  
  502.     IF (CURRENT_OFFSET = 0) THEN
  503.         RETURN (0);
  504.     ENDIF;
  505.  
  506.     vi$move_horizontal (-1);
  507.     IF (CURRENT_CHARACTER <> char_to_find) THEN
  508.         vi$move_horizontal (1);
  509.     ENDIF;
  510.  
  511.     act_count := vi$cur_active_count;
  512.  
  513.     IF char_to_find <> ASCII(27) THEN
  514.         found := 0;
  515.         LOOP
  516.             EXITIF (CURRENT_OFFSET = 0);
  517.             vi$move_horizontal (-1);
  518.             found := 1;
  519.             IF (CURRENT_CHARACTER = char_to_find) THEN
  520.                 act_count := act_count - 1;
  521.                 EXITIF (act_count = 0);
  522.             ENDIF;
  523.             found := 0;
  524.         ENDLOOP;
  525.  
  526.         IF (NOT found) THEN
  527.             POSITION (pos);
  528.             RETURN (0);
  529.         ELSE
  530.             MOVE_HORIZONTAL(1);
  531.         ENDIF;
  532.     ENDIF;
  533.  
  534.     vi$yank_mode := VI$IN_LINE_MODE;
  535.     RETURN (vi$retpos (pos));
  536. ENDPROCEDURE;
  537.  
  538. !
  539. !   The function mapped to 'f'.
  540. !
  541. PROCEDURE vi$_find_char (char_to_find)
  542.  
  543.     LOCAL
  544.         char_val;
  545.  
  546.     char_val := char_to_find;
  547.     vi$beep_position (vi$find_char (char_val), 0, 1);
  548. ENDPROCEDURE;
  549.  
  550. !
  551. !   Function performing task for 'f'.
  552. !
  553. PROCEDURE vi$find_char (ch_to_find)
  554.  
  555.     LOCAL
  556.         char_to_find,
  557.         act_count,
  558.         pos,
  559.         found;
  560.  
  561.     char_to_find := ch_to_find;
  562.     IF char_to_find = 0 THEN
  563.         char_to_find := vi$read_char_to_find;
  564.     ENDIF;
  565.  
  566.     vi$last_s_char := char_to_find;
  567.     vi$last_s_func := "vi$find_char";
  568.  
  569.     act_count := vi$cur_active_count;
  570.  
  571.     IF char_to_find <> ASCII(27) THEN
  572.         pos := MARK(NONE);
  573.         found := 0;
  574.         LOOP
  575.             EXITIF (CURRENT_OFFSET >= LENGTH (vi$current_line));
  576.             MOVE_HORIZONTAL (1);
  577.             found := 1;
  578.             IF (CURRENT_CHARACTER = char_to_find) THEN
  579.                 act_count := act_count - 1;
  580.                 EXITIF (act_count = 0);
  581.             ENDIF;
  582.             found := 0;
  583.         ENDLOOP;
  584.  
  585.         IF (NOT found) THEN
  586.             POSITION (pos);
  587.             RETURN (0);
  588.         ENDIF;
  589.     ELSE
  590.         RETURN (0);
  591.     ENDIF;
  592.  
  593.     vi$yank_mode := VI$IN_LINE_MODE;
  594.     RETURN (vi$retpos(pos));
  595. ENDPROCEDURE;
  596.  
  597. !
  598. !   The function mapped to 'F'.
  599. !
  600. PROCEDURE vi$_back_find_char (char_to_find)
  601.  
  602.     LOCAL
  603.         char_val;
  604.  
  605.     char_val := char_to_find;
  606.     vi$beep_position (vi$back_find_char (char_val), 0, 1);
  607. ENDPROCEDURE;
  608.  
  609. !
  610. !   Function performing task for 'F'.
  611. !
  612. PROCEDURE vi$back_find_char (ch_to_find)
  613.  
  614.     LOCAL
  615.         char_to_find,
  616.         act_count,
  617.         pos,
  618.         found;
  619.  
  620.     char_to_find := ch_to_find;
  621.     IF char_to_find = 0 THEN
  622.         char_to_find := vi$read_char_to_find;
  623.     ENDIF;
  624.  
  625.     vi$last_s_char := char_to_find;
  626.     vi$last_s_func := "vi$back_find_char";
  627.  
  628.     act_count := vi$cur_active_count;
  629.  
  630.     IF char_to_find <> ASCII(27) THEN
  631.         pos := MARK(NONE);
  632.  
  633.         LOOP
  634.             found := 0;
  635.             EXITIF CURRENT_OFFSET = 0;
  636.             vi$move_horizontal (-1);
  637.             found := 1;
  638.             IF (CURRENT_CHARACTER = char_to_find) THEN
  639.                 act_count := act_count - 1;
  640.                 EXITIF act_count = 0;
  641.             ENDIF;
  642.         ENDLOOP;
  643.  
  644.         IF (NOT found) THEN
  645.             POSITION (pos);
  646.             RETURN (0);
  647.         ENDIF;
  648.     ENDIF;
  649.  
  650.     vi$yank_mode := VI$IN_LINE_MODE;
  651.     RETURN (vi$retpos (pos));
  652. ENDPROCEDURE;
  653.  
  654. !
  655. !   Function to read a key, and change TAB_KEY to ASCII (9).  Currently
  656. !   used by f, F, t and T commands only.
  657. !
  658. PROCEDURE vi$read_char_to_find
  659.     LOCAL
  660.         rkey;
  661.  
  662.     rkey := vi$read_a_key;
  663.     IF (rkey = TAB_KEY) THEN
  664.         RETURN (ASCII (9));
  665.     ELSE
  666.         IF (rkey = RET_KEY) THEN
  667.             RETURN (ASCII (13));
  668.         ELSE
  669.             IF (rkey = DEL_KEY) THEN
  670.                 RETURN (ASCII (8));
  671.             ENDIF;
  672.         ENDIF;
  673.     ENDIF;
  674.     RETURN (ASCII (rkey));
  675. ENDPROCEDURE;
  676. !
  677. !   The function mapped to 'G'.
  678. !
  679. PROCEDURE vi$go_to_line
  680.     LOCAL
  681.         opos,
  682.         curline,
  683.         pos;
  684.  
  685.     opos := MARK (NONE);
  686.     IF (vi$beep_position (vi$to_line (vi$active_count), 1, 1) <> 0) THEN
  687.         pos := MARK (NONE);
  688.         POSITION (opos);
  689.         vi$pos_in_middle (pos);
  690.     ENDIF;
  691.  
  692.     vi$active_count := 0;
  693. ENDPROCEDURE;
  694.  
  695. !
  696. !   Move to line in file.  vi$active_count holds the line number to GO TO.
  697. !   If VI$ACTIVE_COUNT is zero, we move to the end of the file.
  698. !
  699. PROCEDURE vi$to_line (cnt)
  700.  
  701.     LOCAL
  702.         this_pos,           ! Saved position in case of botch
  703.         last_line,          ! Last line in the buffer
  704.         win_len;            ! Length of CURRENT_WINDOW
  705.  
  706.     ON_ERROR
  707.         vi$info (FAO ("No such line: !SL", VI$ACTIVE_COUNT));
  708.         POSITION (this_pos);
  709.         cnt := 0;
  710.         RETURN;
  711.     ENDON_ERROR;
  712.  
  713.     this_pos := MARK(NONE);
  714.     POSITION (LINE_BEGIN);
  715.     vi$start_pos := MARK (NONE);
  716.  
  717.     IF cnt = 0 THEN
  718.         POSITION (END_OF (CURRENT_BUFFER));
  719.     ELSE
  720.         last_line := GET_INFO (CURRENT_BUFFER, "RECORD_COUNT");
  721.  
  722.         IF cnt > last_line THEN
  723.             IF last_line > 0 THEN
  724.                 vi$info ("Not that many lines in buffer");
  725.                 POSITION (this_pos);
  726.                 RETURN (0);
  727.             ENDIF;
  728.         ELSE
  729.             POSITION (BEGINNING_OF (CURRENT_BUFFER));
  730.             win_len := GET_INFO (CURRENT_WINDOW, "VISIBLE_LENGTH");
  731.             MOVE_VERTICAL (cnt - 1);
  732.         ENDIF;
  733.     ENDIF;
  734.  
  735.     IF (MARK (NONE) <> END_OF (CURRENT_BUFFER)) THEN
  736.         IF (MARK (NONE) = BEGINNING_OF (CURRENT_BUFFER)) THEN
  737.             vi$new_endpos := MARK (NONE);
  738.         ELSE
  739.             MOVE_VERTICAL (1);
  740.             vi$new_endpos := MARK (NONE);
  741.             MOVE_VERTICAL (-1);
  742.         ENDIF;
  743.     ENDIF;
  744.  
  745.     vi$yank_mode := VI$LINE_MODE;
  746.     RETURN (vi$retpos (this_pos));
  747. ENDPROCEDURE;
  748.  
  749. !
  750. !   Set a marker in the current buffer.
  751. !
  752. PROCEDURE vi$_set_mark
  753.  
  754.     LOCAL
  755.         mark_char,
  756.         mark_name,
  757.         key_pressed;
  758.  
  759.     key_pressed := vi$read_a_key;
  760.  
  761.     mark_char := ASCII (key_pressed);
  762.     IF (INDEX (vi$_lower_chars, mark_char) <> 0) THEN
  763.         mark_name := "vi$mark_" + mark_char;
  764.         EXECUTE (COMPILE (mark_name + " := MARK(NONE);"));
  765.     ELSE
  766.         vi$info ("Invalid marker key!");
  767.     ENDIF;
  768.  
  769. ENDPROCEDURE;
  770.  
  771. !
  772. !   Function mapped to "'" and "`".
  773. !
  774. PROCEDURE vi$_go_to_marker
  775.     LOCAL
  776.         opos,
  777.         pos;
  778.  
  779.     opos := MARK (NONE);
  780.     IF (vi$beep_position (vi$to_marker, 1, 1) <> 0) THEN
  781.         pos := MARK (NONE);
  782.         POSITION (opos);
  783.         vi$pos_in_middle (pos);
  784.     ENDIF;
  785. ENDPROCEDURE;
  786.  
  787. !
  788. !   Function to move the marker indicated by the next keystroke.
  789. !
  790. PROCEDURE vi$to_marker
  791.  
  792.     LOCAL
  793.         mode_key,
  794.         pos,
  795.         mark_name,
  796.         mark_char,
  797.         key_pressed;
  798.  
  799.     ON_ERROR;
  800.         vi$info ("Mark not set!");
  801.         RETURN (0);
  802.     ENDON_ERROR;
  803.  
  804.     mode_key := vi$last_key;
  805.     key_pressed := vi$read_a_key;
  806.  
  807.     mark_char := ASCII (key_pressed);
  808.     IF (INDEX (vi$_lower_chars+"'`", mark_char) = 0) THEN
  809.         vi$info ("Invalid marker key!");
  810.         RETURN (0);
  811.     ENDIF;
  812.  
  813.     pos := MARK (NONE);
  814.     IF (key_pressed <> F11) THEN
  815.         IF (mark_char = "'") OR (mark_char = "`") THEN
  816.             IF (vi$old_place <> 0) THEN
  817.                 IF (GET_INFO (vi$old_place, "BUFFER") = CURRENT_BUFFER) THEN
  818.                     POSITION (vi$old_place);
  819.                 ELSE
  820.                     vi$info ("Previous place not in this buffer!");
  821.                     RETURN (0);
  822.                 ENDIF;
  823.             ELSE
  824.                 vi$info ("No previous mark to return to!");
  825.                 RETURN (0);
  826.             ENDIF;
  827.         ELSE
  828.             mark_name := "vi$mark_" + mark_char;
  829.             EXECUTE (COMPILE ("vi$global_mark := "+mark_name+";"));
  830.  
  831.             IF (vi$global_mark <> 0) AND (GET_INFO (vi$global_mark, "BUFFER") =
  832.                                                             CURRENT_BUFFER) THEN
  833.                 POSITION (vi$global_mark);
  834.                 vi$yank_mode := VI$LINE_MODE;
  835.             ELSE
  836.                 vi$info ("Invalid mark for this buffer!");
  837.                 RETURN (0);
  838.             ENDIF;
  839.         ENDIF;
  840.  
  841.         IF ASCII (mode_key) = "'" THEN
  842.             POSITION (LINE_BEGIN);
  843.             POSITION (vi$first_no_space (0));
  844.         ENDIF;
  845.  
  846.         IF (MARK (NONE) <> END_OF (CURRENT_BUFFER)) THEN
  847.             MOVE_VERTICAL (1);
  848.             vi$new_endpos := MARK (NONE);
  849.             MOVE_VERTICAL (-1);
  850.         ENDIF;
  851.  
  852.         RETURN (vi$retpos (pos));
  853.     ENDIF;
  854.  
  855.     POSITION (pos);
  856.     RETURN (0);
  857. ENDPROCEDURE;
  858.  
  859. !
  860. !   Maintain the repeat count in vi$active_count.  If VI$ACTIVE_COUNT is ZERO,
  861. !   and '0' is typed, this means move to beginning of the line.
  862. !
  863. PROCEDURE vi$repeat_count
  864. a    IF VI$ACTIVE_COUNT = 0 THEN
  865.         vi$active_count := INT (ASCII (KEY_NAME (vi$last_key)));
  866.         IF vi$active_count = 0 THEN
  867.             vi$beep_position (vi$fol, 0, 1);
  868.         ENDIF;
  869.     ELSE
  870.         vi$active_count := vi$active_count * 10 +
  871.                                     INT (ASCII (KEY_NAME (vi$last_key)));
  872.     ENDIF;
  873.  
  874. ENDPROCEDURE;
  875.  
  876. !
  877. !   The function mapped to <CR>.
  878. !
  879. PROCEDURE vi$_next_line
  880.     POSITION (vi$beg_next);
  881. ENDPROCEDURE;
  882.  
  883. !
  884. !   Move the cursor to the beginning of the next line
  885. !
  886. PROCEDURE vi$beg_next
  887.     LOCAL
  888.         pos;
  889.  
  890.     ON_ERROR
  891.         RETURN (MARK (NONE));
  892.     ENDON_ERROR;
  893.  
  894.     pos := MARK (NONE);
  895.     MOVE_VERTICAL (vi$cur_active_count);
  896.     POSITION (LINE_BEGIN);
  897.     POSITION (vi$first_no_space (0));
  898.     vi$yank_mode := VI$LINE_MODE;
  899.     vi$new_offset := 1;
  900.     RETURN (vi$retpos (pos));
  901.  
  902. ENDPROCEDURE;
  903.  
  904. !
  905. !   This function moves to the first non-blank character of a line
  906. !
  907. PROCEDURE vi$first_no_space (use_cur_active)
  908.  
  909.     LOCAL
  910.         pos,
  911.         t_range;
  912.  
  913.     ON_ERROR
  914.         ! Ignore string not found messages.
  915.  
  916.         IF ERROR <> TPU$_STRNOTFOUND THEN
  917.             POSITION (pos);
  918.             RETURN (0);
  919.         ENDIF;
  920.     ENDON_ERROR;
  921.  
  922.     pos := MARK (NONE);
  923.     IF (use_cur_active) THEN
  924.         MOVE_VERTICAL (vi$cur_active_count - 1);
  925.     ENDIF;
  926.     POSITION (LINE_BEGIN);
  927.  
  928.     IF (LENGTH (CURRENT_LINE) > 0) THEN
  929.         IF t_range = 0 THEN
  930.             t_range :=
  931.                 SEARCH (ANCHOR & SPAN (vi$no_space) &
  932.                                         NOTANY(vi$no_space), FORWARD);
  933.         ENDIF;
  934.  
  935.         IF t_range <> 0 THEN
  936.             POSITION (END_OF (t_range));
  937.         ELSE
  938.             ! If that fails, then search for a blank line with extra white
  939.             ! space, and move to the end of the white space.
  940.  
  941.             t_range := SEARCH (ANCHOR & SPAN (vi$no_space), FORWARD);
  942.  
  943.             IF t_range <> 0 THEN
  944.                 POSITION (END_OF (t_range));
  945.             ENDIF;
  946.         ENDIF;
  947.     ENDIF;
  948.  
  949.     vi$yank_mode := VI$IN_LINE_MODE;
  950.     RETURN (vi$retpos (pos));
  951. ENDPROCEDURE;
  952.  
  953. !
  954. !   Move by a section in the indicated direction
  955. !
  956. PROCEDURE vi$_section (dir)
  957.     LOCAL
  958.         ch;
  959.  
  960.     ch := vi$read_a_key;
  961.     IF ((ASCII(ch) = "]") AND (dir = 1)) OR
  962.         ((ASCII(ch) = "[") AND (dir = -1)) THEN
  963.         vi$beep_position (vi$section (dir), 1, 1);
  964.     ELSE
  965.         vi$beep;
  966.     ENDIF;
  967. ENDPROCEDURE;
  968.  
  969. !
  970. !   Sound a bell.
  971. !
  972. PROCEDURE vi$beep
  973.     LOCAL
  974.         ln,
  975.         pos;
  976.  
  977.     IF (vi$error_bells = 0) THEN
  978.         RETURN;
  979.     ENDIF;
  980.  
  981.     pos := MARK (NONE);
  982.     POSITION (message_buffer);
  983.     ln := vi$current_line;
  984.     SET (BELL, ALL, ON);
  985.     POSITION (pos);
  986.     vi$info (ln);
  987.     SET (BELL, ALL, OFF);
  988.     SET (BELL, BROADCAST, ON);
  989. ENDPROCEDURE;
  990.  
  991. !
  992. !   Mapped to '}' and '{', moves by a paragraph in the indicated direction.
  993. !
  994. PROCEDURE vi$_paragraph(dir)
  995.     vi$beep_position (vi$paragraph(dir), 1, 1);
  996. ENDPROCEDURE;
  997.  
  998. !
  999. !   Mapped to ( moves backward a sentence
  1000. !
  1001. PROCEDURE vi$_begin_sentence
  1002.     vi$beep_position (vi$begin_sentence, 1, 1);
  1003. ENDPROCEDURE;
  1004.  
  1005. !
  1006. !   Mapped to ) moves forward a sentence
  1007. !
  1008. PROCEDURE vi$_end_sentence
  1009.     vi$beep_position (vi$end_sentence, 1, 1);
  1010. ENDPROCEDURE;
  1011.  
  1012. !
  1013. !   Move backward a sentence.
  1014. !
  1015. PROCEDURE vi$begin_sentence
  1016.     LOCAL
  1017.         rng,
  1018.         spos,
  1019.         pos;
  1020.  
  1021.     ON_ERROR;
  1022.     ENDON_ERROR;
  1023.  
  1024.     pos := MARK (NONE);
  1025.  
  1026.     MOVE_HORIZONTAL (-1);
  1027.  
  1028.     LOOP;
  1029.         rng := SEARCH (
  1030.             (("" | " " | ASCII (9)) & ANY (vi$_upper_chars)),
  1031.             REVERSE, EXACT);
  1032.  
  1033.         EXITIF rng = 0;
  1034.  
  1035.         POSITION (BEGINNING_OF (rng));
  1036.         IF INDEX (vi$_space_tab, CURRENT_CHARACTER) = 0 THEN
  1037.             MOVE_HORIZONTAL (-1);
  1038.         ENDIF;
  1039.         IF INDEX (vi$_space_tab, CURRENT_CHARACTER) <> 0 THEN
  1040.             IF (CURRENT_CHARACTER = " ") THEN
  1041.                 MOVE_HORIZONTAL (-1);
  1042.                 IF INDEX (vi$_space_tab, CURRENT_CHARACTER) <> 0 THEN
  1043.                     MOVE_HORIZONTAL (-1);
  1044.                     IF INDEX ("?.!", CURRENT_CHARACTER) <> 0 THEN
  1045.                         MOVE_HORIZONTAL (3);
  1046.                         RETURN (vi$retpos (pos));
  1047.                     ENDIF;
  1048.                 ENDIF;
  1049.             ELSE
  1050.                 MOVE_HORIZONTAL (1);
  1051.                 RETURN (vi$retpos (pos));
  1052.             ENDIF;
  1053.         ENDIF;
  1054.         POSITION (BEGINNING_OF (rng));
  1055.         MOVE_HORIZONTAL (-1);
  1056.     ENDLOOP;
  1057.  
  1058.     RETURN (0);
  1059. ENDPROCEDURE;
  1060.  
  1061. !
  1062. !   Move to next paragraph
  1063. !
  1064. PROCEDURE vi$paragraph (dir)
  1065.     RETURN (vi$para_sect (dir, vi$para_pat));
  1066. ENDPROCEDURE;
  1067.  
  1068. !
  1069. !   Find next paragraph or section.
  1070. !
  1071. PROCEDURE vi$para_sect (dir, pat)
  1072.     LOCAL
  1073.         loc,
  1074.         direct,
  1075.         pos;
  1076.  
  1077.     pos := MARK (NONE);
  1078.  
  1079.     IF (dir < 0) THEN
  1080.         direct := REVERSE;
  1081.         MOVE_VERTICAL (-1);
  1082.     ELSE
  1083.         direct := FORWARD;
  1084.         MOVE_VERTICAL (1);
  1085.     ENDIF;
  1086.  
  1087.     loc := SEARCH (pat, direct, NO_EXACT);
  1088.  
  1089.     IF (loc <> 0) THEN
  1090.         RETURN (BEGINNING_OF (loc));
  1091.     ENDIF;
  1092.  
  1093.     POSITION (pos);
  1094.     RETURN (0);
  1095. ENDPROCEDURE;
  1096.  
  1097. !
  1098. !   Move to next section
  1099. !
  1100. PROCEDURE vi$section (dir)
  1101.     RETURN (vi$para_sect (dir, vi$sect_pat));
  1102. ENDPROCEDURE;
  1103.  
  1104. !
  1105. !   Move forward a sentence.
  1106. !
  1107. PROCEDURE vi$end_sentence
  1108.     LOCAL
  1109.         rng,
  1110.         spos,
  1111.         pos;
  1112.  
  1113.     ON_ERROR;
  1114.     ENDON_ERROR;
  1115.  
  1116.     pos := MARK (NONE);
  1117.  
  1118.     MOVE_HORIZONTAL (1);
  1119.  
  1120.     LOOP;
  1121.         rng := SEARCH (ANY (vi$_upper_chars), FORWARD, EXACT);
  1122.  
  1123.         EXITIF rng = 0;
  1124.  
  1125.         POSITION (BEGINNING_OF (rng));
  1126.         IF INDEX (vi$_space_tab, CURRENT_CHARACTER) = 0 THEN
  1127.             MOVE_HORIZONTAL (-1);
  1128.         ENDIF;
  1129.         IF INDEX (vi$_space_tab, CURRENT_CHARACTER) <> 0 THEN
  1130.             IF (CURRENT_CHARACTER = " ") THEN
  1131.                 MOVE_HORIZONTAL (-1);
  1132.                 IF INDEX (vi$_space_tab, CURRENT_CHARACTER) <> 0 THEN
  1133.                     MOVE_HORIZONTAL (-1);
  1134.                     IF INDEX ("?.!", CURRENT_CHARACTER) <> 0 THEN
  1135.                         MOVE_HORIZONTAL (3);
  1136.                         RETURN (vi$retpos (pos));
  1137.                     ENDIF;
  1138.                 ENDIF;
  1139.             ELSE
  1140.                 MOVE_HORIZONTAL (1);
  1141.                 RETURN (vi$retpos (pos));
  1142.             ENDIF;
  1143.         ENDIF;
  1144.         POSITION (BEGINNING_OF (rng));
  1145.         MOVE_HORIZONTAL (1);
  1146.     ENDLOOP;
  1147.  
  1148.     RETURN (0);
  1149. ENDPROCEDURE;
  1150.  
  1151. !
  1152. !   This function returns the value in vi$active count.  It takes into
  1153. !   account that when vi$active_count is zero, it should really be
  1154. !   one.
  1155. !
  1156. PROCEDURE vi$cur_active_count
  1157.     LOCAL
  1158.         resp,
  1159.         old_cnt;
  1160.  
  1161.     old_cnt := vi$active_count;
  1162.     vi$active_count := 0;
  1163.     IF old_cnt <= 0 THEN
  1164.         old_cnt := 1;
  1165.     ENDIF;
  1166.  
  1167.     RETURN (old_cnt);
  1168. ENDPROCEDURE;
  1169.  
  1170. !
  1171. !   The function mapped to 'p'.
  1172. !
  1173. PROCEDURE vi$put_after (dest_buf)
  1174.  
  1175.     LOCAL
  1176.         source,
  1177.         pos;
  1178.  
  1179.     source := vi$cur_text;
  1180.  
  1181.     IF (GET_INFO (dest_buf, "TYPE") = BUFFER) THEN
  1182.         source := dest_buf;
  1183.     ENDIF;
  1184.  
  1185.     IF (GET_INFO (source, "TYPE") = BUFFER) THEN
  1186.         pos := MARK (NONE);
  1187.         POSITION (BEGINNING_OF (source));
  1188.         vi$yank_mode := INT (vi$current_line);
  1189.         POSITION (pos);
  1190.     ENDIF;
  1191.  
  1192.     IF (source = "") THEN
  1193.         RETURN;
  1194.     ENDIF;
  1195.  
  1196.     IF (vi$yank_mode = VI$LINE_MODE) THEN
  1197.         IF (MARK(NONE) <> END_OF (CURRENT_BUFFER)) THEN
  1198.             MOVE_VERTICAL (1);
  1199.         ENDIF;
  1200.     ELSE
  1201.         IF (LENGTH (CURRENT_LINE) > 0) THEN
  1202.             MOVE_HORIZONTAL (1);
  1203.         ENDIF;
  1204.     ENDIF;
  1205.  
  1206.     vi$put_here (VI$AFTER, source);
  1207. ENDPROCEDURE;
  1208.  
  1209. !
  1210. !   The function mapped to 'P'.
  1211. !
  1212. PROCEDURE vi$put_here (here_or_below, dest_buf)
  1213.     LOCAL
  1214.         olen,
  1215.         source,
  1216.         pos;
  1217.  
  1218.     source := vi$cur_text;
  1219.     olen := GET_INFO (CURRENT_BUFFER, "RECORD_COUNT");
  1220.  
  1221.     IF (GET_INFO (dest_buf, "TYPE") = BUFFER) THEN
  1222.         source := dest_buf;
  1223.     ENDIF;
  1224.  
  1225.     IF (GET_INFO (source, "TYPE") = BUFFER) THEN
  1226.         pos := MARK (NONE);
  1227.         POSITION (BEGINNING_OF (source));
  1228.         IF (MARK (NONE) = END_OF (source)) THEN
  1229.             RETURN;
  1230.         ENDIF;
  1231.         vi$yank_mode := INT (vi$current_line);
  1232.         ERASE_LINE;
  1233.         POSITION (pos);
  1234.     ELSE
  1235.         IF (source = "") THEN
  1236.             RETURN;
  1237.         ENDIF;
  1238.     ENDIF;
  1239.  
  1240.     IF source = 0 THEN
  1241.         vi$info ("Bad buffer for put!");
  1242.         RETURN;
  1243.     ENDIF;
  1244.  
  1245.     IF (vi$yank_mode = VI$LINE_MODE) THEN
  1246.         POSITION (LINE_BEGIN);
  1247.     ENDIF;
  1248.  
  1249.     pos := vi$get_undo_start;
  1250.  
  1251.     COPY_TEXT (source);
  1252.     APPEND_LINE;
  1253.     MOVE_HORIZONTAL (-1);
  1254.     vi$undo_end := MARK (NONE);
  1255.     MOVE_HORIZONTAL (1);
  1256.  
  1257.     vi$kill_undo;
  1258.  
  1259.     IF (here_or_below = VI$AFTER) AND (vi$yank_mode = VI$LINE_MODE) THEN
  1260.         POSITION (LINE_BEGIN);
  1261.     ENDIF;
  1262.  
  1263.     vi$undo_start := vi$set_undo_start (pos);
  1264.  
  1265.     ! Put the mode back into the buffer.
  1266.  
  1267.     IF (GET_INFO (source, "TYPE") = BUFFER) THEN
  1268.         POSITION (BEGINNING_OF (source));
  1269.         COPY_TEXT (STR (vi$yank_mode));
  1270.         SPLIT_LINE;
  1271.         POSITION (vi$undo_start);
  1272.     ENDIF;
  1273.  
  1274.     IF (here_or_below = VI$AFTER) AND (vi$yank_mode = VI$IN_LINE_MODE) THEN
  1275.         POSITION (vi$undo_end);
  1276.     ENDIF;
  1277.  
  1278.     vi$check_length (olen);
  1279. ENDPROCEDURE;
  1280.  
  1281. !
  1282. !   Function mapped to 'o'.
  1283. !
  1284. PROCEDURE vi$open_below
  1285.     LOCAL
  1286.         uline;
  1287.  
  1288.     ON_ERROR
  1289.         ! Ignore attempt to move past EOB errors
  1290.     ENDON_ERROR;
  1291.  
  1292.     uline := vi$cur_line_no;
  1293.     MOVE_VERTICAL (1);
  1294.     vi$open_here;
  1295.     vi$undo_line := uline;
  1296.  
  1297. ENDPROCEDURE;
  1298.  
  1299. !
  1300. !   Function mapped to 'O'
  1301. !
  1302. PROCEDURE vi$open_here
  1303.  
  1304.     LOCAL
  1305.         uline,
  1306.         offs,
  1307.         cnt,
  1308.         epos,
  1309.         spos;
  1310.  
  1311.     uline := vi$cur_line_no;
  1312.     offs := CURRENT_OFFSET;
  1313.  
  1314.     POSITION (LINE_BEGIN);
  1315.  
  1316.     IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN
  1317.         MOVE_HORIZONTAL (-1);
  1318.         spos := MARK (NONE);
  1319.         MOVE_HORIZONTAL (1);
  1320.     ELSE
  1321.         spos := 0;
  1322.     ENDIF;
  1323.  
  1324.     SPLIT_LINE;
  1325.  
  1326.     MOVE_VERTICAL (-1);
  1327.  
  1328.     cnt := vi$while_not_esc;
  1329.  
  1330.     IF (cnt <> 0) THEN
  1331.         IF (LENGTH(vi$current_line) > 0) THEN
  1332.             MOVE_HORIZONTAL (1);
  1333.         ENDIF;
  1334.     ENDIF;
  1335.     epos := MARK (NONE);
  1336.     vi$undo_end := MARK (NONE);
  1337.  
  1338.     vi$undo_start := vi$set_undo_start (spos);
  1339.  
  1340.     POSITION (epos);
  1341.  
  1342.     vi$kill_undo;
  1343.  
  1344.     vi$undo_line := uline;
  1345.     vi$undo_offset := offs;
  1346. ENDPROCEDURE;
  1347.  
  1348. !
  1349. !   This function guards the right margin, and the end of the buffer so
  1350. !   that the cursor never is displayed past those boundries.
  1351. !
  1352. PROCEDURE vi$check_rmarg
  1353.  
  1354.     ON_ERROR;
  1355.         ! ignore "Can't return line and end of buffer" messages
  1356.         RETURN;
  1357.     ENDON_ERROR;
  1358.  
  1359.     IF (LENGTH (vi$current_line) > 0) THEN
  1360.         IF (CURRENT_OFFSET = LENGTH (vi$current_line)) THEN
  1361.             MOVE_HORIZONTAL (-1);
  1362.         ENDIF;
  1363.     ENDIF;
  1364.  
  1365.     IF (MARK (NONE) = END_OF (CURRENT_BUFFER)) THEN
  1366.         MOVE_VERTICAL (-1);
  1367.     ENDIF;
  1368. ENDPROCEDURE;
  1369.  
  1370. !
  1371. !   The function mapped to 'h'.
  1372. !
  1373. PROCEDURE vi$move_left
  1374.     vi$beep_position (vi$left, 0, 1);
  1375. ENDPROCEDURE;
  1376.  
  1377. !
  1378. !   The function mapped to 'l'.
  1379. !
  1380. PROCEDURE vi$move_right
  1381.     vi$beep_position (vi$right, 0, 1);
  1382. ENDPROCEDURE;
  1383.  
  1384. !
  1385. !   The function mapped to 'j'
  1386. !
  1387. PROCEDURE vi$move_down
  1388.     LOCAL
  1389.         save_mark;
  1390.  
  1391.     save_mark := 0;
  1392.  
  1393.     IF (vi$active_count >= vi$report) THEN
  1394.         save_mark := 1;
  1395.     ENDIF;
  1396.  
  1397.     vi$beep_position (vi$downline (0), save_mark, 1);
  1398. ENDPROCEDURE;
  1399.  
  1400. !
  1401. !   The function mapped to 'k'.
  1402. !
  1403. PROCEDURE vi$move_up
  1404.     LOCAL
  1405.         save_mark;
  1406.  
  1407.     save_mark := 0;
  1408.  
  1409.     IF (vi$active_count >= vi$report) THEN
  1410.         save_mark := 1;
  1411.     ENDIF;
  1412.  
  1413.     vi$beep_position (vi$upline, save_mark, 1);
  1414. ENDPROCEDURE;
  1415.  
  1416. !
  1417. !   The function mapped to 'i'.
  1418. !
  1419. PROCEDURE vi$insert_here
  1420.     LOCAL
  1421.         act_cnt,
  1422.         rnge,
  1423.         ccnt,
  1424.         epos,
  1425.         spos;
  1426.  
  1427.     vi$kill_undo;
  1428.  
  1429.     IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN
  1430.         MOVE_HORIZONTAL (-1);
  1431.         spos := MARK (NONE);
  1432.         MOVE_HORIZONTAL (1);
  1433.     ELSE
  1434.         spos := 0;
  1435.     ENDIF;
  1436.  
  1437.     vi$undo_start := MARK (NONE);
  1438.  
  1439.     ccnt := vi$while_not_esc;
  1440.  
  1441.     vi$undo_end := 0;
  1442.  
  1443.     IF (ccnt > 0) THEN
  1444.         epos := MARK (NONE);
  1445.         IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN
  1446.             MOVE_HORIZONTAL (1);
  1447.         ENDIF;
  1448.     ELSE
  1449.         epos := 0;
  1450.         IF (CURRENT_OFFSET <> 0) THEN
  1451.             MOVE_HORIZONTAL (-1);
  1452.         ENDIF;
  1453.     ENDIF;
  1454.  
  1455.     act_cnt := vi$cur_active_count;
  1456.     IF epos <> 0 THEN
  1457.  
  1458.         IF spos <> 0 THEN
  1459.             POSITION (spos);
  1460.             MOVE_HORIZONTAL (1);
  1461.         ELSE
  1462.             POSITION (BEGINNING_OF (CURRENT_BUFFER));
  1463.         ENDIF;
  1464.         vi$undo_start := MARK (NONE);
  1465.  
  1466.         POSITION (epos);
  1467.  
  1468.         IF (vi$undo_start = 0) OR (epos = 0) THEN
  1469.             vi$info ("Ooops, bad markers in vi$insert_here");
  1470.             RETURN ;
  1471.         ENDIF;
  1472.  
  1473.         rnge := CREATE_RANGE (vi$undo_start, epos, NONE);
  1474.  
  1475.         LOOP
  1476.             EXITIF act_cnt < 2;
  1477.             MOVE_HORIZONTAL (1);
  1478.  
  1479.             IF rnge = 0 THEN
  1480.                 vi$info ("Ooops, generated a bad range in vi$insert_here");
  1481.                 RETURN ;
  1482.             ENDIF;
  1483.  
  1484.             COPY_TEXT (rnge);
  1485.             act_cnt := act_cnt - 1;
  1486.             MOVE_HORIZONTAL (-1);
  1487.         ENDLOOP;
  1488.  
  1489.         vi$undo_end := MARK (NONE);
  1490.         IF (CURRENT_OFFSET = LENGTH (vi$current_line)) THEN
  1491.             MOVE_HORIZONTAL (1);
  1492.         ENDIF;
  1493.     ENDIF;
  1494. ENDPROCEDURE;
  1495.  
  1496. !
  1497. !   The function mapped to 'I'
  1498. !
  1499. PROCEDURE vi$insert_at_begin
  1500.  
  1501.     POSITION (LINE_BEGIN);
  1502.     vi$_bol (0);
  1503.     vi$insert_here;
  1504.  
  1505. ENDPROCEDURE;
  1506.  
  1507. !
  1508. !   The function mapped to 'a'
  1509. !
  1510. PROCEDURE vi$insert_after
  1511.  
  1512.     LOCAL
  1513.         cline,
  1514. $$EOD$$
  1515.